package com.zeus.core.config.listener;

import com.zeus.common.log.ZeusLoggerConfig;
import com.zeus.core.config.spring.ZeusApplicationContextHelper;
import com.zeus.core.context.ZeusContext;
import com.zeus.core.factory.ZeusFactory;
import com.zeus.core.log.config.Log4j2Config;
import com.zeus.core.log.config.Log4jConfig;
import com.zeus.core.log.config.LogbackConfig;
import com.zeus.core.open.config.ZeusInfo;
import com.zeus.core.report.ZeusReportClient;
import com.zeus.core.report.ZeusReportServiceShutdownClient;
import com.zeus.core.report.ZeusReportServiceStartClient;
import com.zeus.core.task.GatherTask;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.util.Objects;


@Slf4j
public class ZeusMonitorContextStartEventListener implements ApplicationListener<ContextRefreshedEvent> {

    /**
     * 是否已初始化
     */
    private static volatile boolean initialized = false;

    /**
     * Spring容器初始化完成会触发该事件
     *
     * @param event ApplicationContext刷新事件
     * @author f1ybear_wang  2021/5/13 17:52
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {

        if (!initialized) {
            if (Objects.isNull(ZeusApplicationContextHelper.getApplicationContext())) {
                return;
            }
            initialized = true;
            // 获取全局配置
            if (log.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                log.warn("### Zeus服务[" + ZeusInfo.getVersion() + "], 准备初始化监控配置信息");
            }

            // 初始化上下文
            ZeusContext.init();

            // V2聚合任务初始化
            GatherTask.init();

            // 初始化SPI服务
            ZeusFactory.initSpiService();

            // 初始化自定义appender配置信息
            initLogMonitorConfig();

            // 服务启动、关闭通知
            serviceUpDownNotify();

            if (log.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                log.warn("### Zeus服务[" + ZeusInfo.getVersion() + "], 初始化监控配置信息完成");
            }
        }
    }

    /**
     * 初始化自定义appender配置信息
     *
     * @author wangfeixiong126@gmail.com  2021/5/30 17:58
     */
    private void initLogMonitorConfig() {
        boolean initializedLog4j = false;
        boolean initializedLogback = false;
        boolean initializedLog4j2 = false;


        try {
            // 先初始化log4j
            initializedLog4j = Log4jConfig.init();
        } catch (Throwable ignored) {
            // 忽略
        }

        try {
            // 再初始化logback
            initializedLogback = LogbackConfig.init();
        } catch (Throwable ignored) {
            // 忽略
        }

        try {
            // 再初始化logback
            initializedLog4j2 = Log4j2Config.init();
        } catch (Throwable ignored) {
            // 忽略
        }
        
        if (initializedLog4j || initializedLogback || initializedLog4j2) {
            if (log.isInfoEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                log.info(">>> Zeus服务, 监控配置信息初始化完成!");
            }
            return;
        }
        // 上边logback和log4j都未找到配置文件，则加载失败
        if (log.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
            log.warn("### Zeus日志监控模块, 日志监控配置信息初始化失败，未找到log4j配置和logback配置");
        }
    }

    /**
     * 服务启动、关闭通知
     *
     * @author wangfeixiong126@gmail.com  2021/9/6 4:20 下午
     */
    private void serviceUpDownNotify() {
        try {
            // 发送服务启动通知
            if (ZeusContext.getContext().startNotifyEnable()) {
                ZeusReportClient startClient = new ZeusReportServiceStartClient();
                startClient.complete();
            }

            // JVM关闭  不能很好的支持 /actuator/shutdown
            serviceDownNotify();
        } catch (Throwable t) {
            if (log.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                log.warn("### Zeus监控服务, 发送服务启动、关闭通知出现异常 >> errMsg = {}", t.getMessage());
            }
        }
    }

    @Deprecated
    private static void serviceDownNotify() {
        if (ClassUtils.isPresent("org.springframework.boot.actuate.endpoint.ShutdownEndpoint"
                , ZeusMonitorContextStartEventListener.class.getClassLoader())) {
            return;
        }
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                ZeusReportClient client = new ZeusReportServiceShutdownClient();
                if (ZeusContext.getContext().shutdownNotifyEnable()) {
                    client.complete();
                }
            } catch (Throwable throwable) {
                if (log.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                    log.warn("### Zeus监控服务, 发送服务关闭通知出现异常 >> errMsg = {}", throwable.getMessage());
                }
            }
        }));
    }
}
